package org.bulldog.playlist.notice;

import org.bulldog.playlist.PlayListener;
import org.bulldog.playlist.util.DateUtil;
import org.bulldog.playlist.util.ThreadUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 通知播表
 *
 * @author zhanghongbin
 * @version 1.0
 */
public final class NoticePlayList {

    private static List<Notice> playList;  //播表

    private static int playIndex = 0;//播放索引

    private static boolean rotationFlag = true;
    //通知结束发送标识
    private static boolean noticeEndSendFlag = true;

    static {
        playList = new ArrayList();
    }

    private NoticePlayList() {

    }

    public static boolean isEmpty() {
        return playList.isEmpty();
    }

    public static List<Notice> getPlayList() {
        return Collections.synchronizedList(playList);
    }

    /**
     * 通知播表构建
     *
     * @param noticeList
     */
    public static void build(List<Notice> noticeList, PlayListener playListener) {
        synchronized (NoticePlayList.class) {
            playList.clear();
            playIndex = 0;
            List<Notice> notices = NoticePlayListBuilder.INSTANCE.build(noticeList);
            playList.addAll(notices);
            notices.clear();
            noticeEndSendFlag = false;
            try {
                playListener.onPlayListBuildFinish(PlayListener.Type.NOTICE, playList);
            } catch (Exception e) {
                e.printStackTrace();
            }
            NoticePlayList.class.notifyAll();
        }
    }

    private static void _run(PlayListener playListener) {
        synchronized (NoticePlayList.class) {
            final Notice notice = playList.get(playIndex);
            sendNotice(notice, 1, playListener);
            playIndex = playIndex + 1;
            //每次需要重置为true，只有调用notifyAll 的时候才为 false
            noticeEndSendFlag = true;
            try {
                NoticePlayList.class.wait(notice.getPlayDuration() * 1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (noticeEndSendFlag) {
                sendNotice(notice, 0, playListener);
            }
        }
    }

    private static void sendNotice(final Notice notice, final int status, final PlayListener playListener) {
        if (!notice.getId().equals("-1")) {
            ThreadUtil.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        notice.setStatus(status);
                        playListener.onPlay(PlayListener.Type.NOTICE, notice);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    /**
     * 通知播表运行
     *
     * @param playListener
     */
    public static void run(PlayListener playListener) {
        while (rotationFlag) {
            if (playList.size() > playIndex) {
                _run(playListener);
            } else {
                await();
            }
        }
    }

    /**
     * 重新发送通知(用于节目切换)
     */
    public static void backroll() {
        synchronized (NoticePlayList.class) {
            if (playList.isEmpty()) return;
            String currentTime = DateUtil.now();
            Notice notice = new Notice();
            notice.setStartTime(currentTime);
            int n = playList.indexOf(notice);
            //点播playIndex = Integer.MAX_VALUE
            if (playIndex == Integer.MAX_VALUE) {
                recover(n, currentTime);
                noticeEndSendFlag = true;
                NoticePlayList.class.notifyAll();
            } else if (n != -1 && repeat(n, currentTime)) {
                //设置不发送通知结束信息
                noticeEndSendFlag = false;
                NoticePlayList.class.notifyAll();
            }
        }
    }

    /**
     * 继续播放
     * @param n
     * @param currentTime
     * @return
     */
    private static boolean repeat(int n, String currentTime) {
        Notice notice = playList.get(n);
        //占位通知
        if (notice.getId().equals("-1")) {
            return false;
        }
        int value = DateUtil.minus(currentTime, notice.getEndTime());
        if (value < NoticePlayListBuilder.LIMIT_SECOND) {
            if (value - 1 > 0) {
                try {
                    Thread.sleep(1000 * (value - 1));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return true;
        }
        notice.setPlayDuration(value);
        playIndex = n;
        return true;
    }

    /**
     * 恢复通知播表执行
     */
    private static void recover(int n, String currentTime) {
        if (n != -1) {
            Notice notice = playList.get(n);
            //计算当前时间和结束时间的差值
            int value = DateUtil.minus(currentTime, notice.getEndTime());
            //如果差值大于 10秒则播放在当前时间范围内的节目,小于10秒播放没有意义时间太短
            if (value >= NoticePlayListBuilder.LIMIT_SECOND) {
                notice.setDemandEndTime(currentTime);
                notice.setPlayDuration(value);
                playIndex = n;
            } else {
                if (value - 1 > 0) {
                    try {
                        Thread.sleep(1000 * (value - 1));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                playIndex = n + 1 >= playList.size() ? playList.size() : n + 1;
            }
        } else {
            playIndex = playList.size();
        }
    }

    /**
     * 防止空转
     */
    private static void await() {
        synchronized (NoticePlayList.class) {
            try {
                NoticePlayList.class.wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 暂停
     */
    public static void pause() {
        synchronized (NoticePlayList.class) {
            playIndex = Integer.MAX_VALUE;
            noticeEndSendFlag = false;
            NoticePlayList.class.notifyAll();
        }
    }

    /**
     * 根据id获取通知内容
     *
     * @param id
     * @return
     */
    public static String findContent(String id) {
        synchronized (NoticePlayList.class) {
            for (Notice notice : playList) {
                if (notice.getId().equals(id)) {
                    return notice.getContent();
                }
            }
        }
        return "";
    }

}
